package com.pointi.emoEngine;

public class DSP_SVM
{
	public double len_weight [] ;
	public double bias [] ;
	public double weight [] ;
	public double xsup [][] ;

	DSP_SVM() {
	}
	
	public void SVM(double [] x, double [] result, int LEVEL, double [] _weight, double [][] _xsup)
	{
		int class_main ;
		int class_sub ;
		int class_num = LEVEL ;

		double [] D_ij = new double [LEVEL] ;

		int pair = 0 ;
		int pair_point= 0 ;

		double [][] sup ;
		int dim = 28 ;

		int i, j , ii ;
		int start_pos, end_pos ;

		double y ;
		double gamma = 10 ;

		double [] kernel;

//*
		//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
		//		Parameter Option (2012-12-26)
		//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
		//		*	SET				*	SIZE
		//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
		//		0	Extra Small		-	3260
		//		1	Small				-	7306
		//		2	Meduim			-	15370
		//		3	Large			-	30566
		//		4	Extra Large	-	61690
		//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

		int pOption = 0 ;
		switch (pOption)
		{
		case 0 :
			len_weight = new double [] {318, 234, 237, 318, 251, 266, 234, 251, 324, 237, 266, 324};
			bias = new double [] {0.118465345588, 1.391662839160, -0.613733592131, -0.118465345591, 0.798278938432, 1.993706496672, -1.391662839156, -0.798278938433, -1.305477462696, 0.613733592132, -1.993706496668, 1.305477462697};
			break ;
		case 1 :
			len_weight = new double [] {736, 492, 527, 736, 552, 567, 492, 552, 779, 527, 567, 779};
			bias = new double [] {-1.027556741461, 1.679740169864, 1.279828868839, 1.027556741468, 3.388969076742, 3.268280107262, -1.679740169863, -3.388969076738, -1.725829465359, -1.279828868841, -3.268280107273, 1.725829465352};
			break ;
		case 2 :
			len_weight = new double [] {1670, 979, 1046, 1670, 1087, 1192, 979, 1087, 1711, 1046, 1192, 1711};
			bias = new double [] {-2.121289988718, 2.334336317469, 1.646162346476, 2.121289988712, 5.144621458847, 4.860955612375, -2.334336317462, -5.144621458842, -1.450558169210, -1.646162346483, -4.860955612378, 1.450558169228};
			break ;
		case 3 :
			len_weight = new double [] {3453, 1890, 2003, 3453, 2135, 2273, 1890, 2135, 3529, 2003, 2273, 3529};
			bias = new double [] {-2.677895203876, 5.166019257400, 3.789158187488, 2.677895203871, 7.652173739483, 8.195723155705, -5.166019257393, -7.652173739480, -2.891448511264, -3.789158187523, -8.195723155707, 2.891448511292};
			break ;
		case 4 :
			len_weight = new double [] {7186, 3966, 4310, 7186, 3914, 4292, 3966, 3914, 7177, 4310, 4292, 7177};
			bias = new double []  {-0.612707792376, 9.130278722397, 4.709115378567, 0.612707792394, 8.966115784838, 8.408490698622, -9.130278722439, -8.966115784859, -7.712857789037, -4.709115378626, -8.408490698608, 7.712857789113};
			break ;
		default:
			len_weight = new double [] {1670, 979, 1046, 1670, 1087, 1192, 979, 1087, 1711, 1046, 1192, 1711};
			bias = new double [] {-2.121289988718, 2.334336317469, 1.646162346476, 2.121289988712, 5.144621458847, 4.860955612375, -2.334336317462, -5.144621458842, -1.450558169210, -1.646162346483, -4.860955612378, 1.450558169228};
		}
/*/
		//--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
		// LEVEL 4 only (2012-11-24)
		//--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
		len_weight = new double [] {3065, 1796, 3194, 3065, 2635, 4172, 1796, 2635, 4578, 3194, 4172, 4578};
		bias = new double [] {-11.177138798321, 17.102341452760, -7.048142180515, 11.177138798321, 24.383160853427, 8.031261285391, -17.102341452748, -24.383160853413, -16.546149878454, 7.048142180509, -8.031261285397, 16.546149878480};
//*/
		weight = _weight ;
		xsup = _xsup ;
		dim = 13 ;
		//--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  

		for (class_main = 0 ; class_main < class_num ; class_main++)
		{
			for (class_sub = 0 ; class_sub < class_num ; class_sub++)
			{
				if (class_main == class_sub) { D_ij[class_sub] = 1 ; }
				else
				{
					pair_point += (int)len_weight[pair] ;
					sup = new double [(int)len_weight[pair]][] ;
					for (i = 0 ; i < len_weight[pair] ; i++) { sup[i] = new double [dim] ; }
					start_pos = (int)(pair_point - len_weight[pair]) ;
					end_pos = pair_point ;
					ii = 0 ;
					for (i = start_pos ; i < end_pos ; i ++)
					{
						for (j = 0 ; j < dim ; j++) { sup[ii][j] = xsup[i][j] ; }
						ii++ ;
					}
					kernel = new double [(int)len_weight[pair]] ;
					rbf_kernel(kernel, x, sup, dim, pair, gamma) ; 
					y = 0.0 ;
					for (i = 0 ; i < len_weight[pair] ; i++) { y += kernel[i] * weight[start_pos + i] ; }
					D_ij[class_sub] = y + bias[pair] ;
					sup = null ;
					kernel = null ;		
					pair ++ ;
				}
			}
			result[class_main] = D_ij[class_main] ;
			for (i = 0 ; i < class_num ; i++) { if (D_ij[i] < result[class_main]) result[class_main] = D_ij[i] ; }
		}
	}

	public void rbf_kernel(double [] ps, double [] x, double [][] sup, int dim, int pair ,double gamma)
	{
		int i, j ;
		double [] metric = new double [28] ;
		double normx = 0 ;	
		double [] normsup = new double [(int)len_weight[pair]] ; 

		for (i = 0 ; i < dim ; i ++) { metric[i] = (1/(gamma*gamma)) ; 	}

		for (i = 0 ; i < len_weight[pair] ; i ++)
		{	
			ps[i] = 0.0 ;
			for (j = 0; j < dim ; j++) { ps[i] += x[j] * metric[j] * sup[i][j] ; }
		}

		normx = 0 ;
		for (i = 0 ; i < dim ; i++) { normx += (x[i] * x[i]) * metric[i] ; }

		for (i = 0 ; i < len_weight[pair] ; i ++)
		{		
			normsup[i] = 0.0 ;
			for (j = 0 ; j < dim ; j++) { normsup[i] += metric[j] * (sup[i][j] * sup[i][j]) ; }
		}

		for (i = 0 ; i < len_weight[pair] ; i ++) { ps[i] = Math.exp(-((-2 * ps[i]) + normx + normsup[i]) / 2) ; }
		normsup = null ;
	}
}